<!-- 图片上传的组件 -->
<!-- multiple   // 可以多选 -->
<!-- :before-upload="handleBeforeUpload"  // 文件上传之前进行的操作 -->
<!-- :on-exceed="handleImgChange"   // 文件数量超过限制时调用 -->
<!-- on-remove -->
<template>
  <div class="component-upload-image">
    <el-upload
      class="avatar-uploader"
      ref="uploadRef"
      action="#"
      show-file-list
      list-type="picture-card"
      :on-preview="handlePictureCardPreview"
      :on-change="handleImgChange"
      :on-exceed="handleExceed"
      :on-remove="handleRemove"
      :file-list="fileList"
      :auto-upload="false"
      :limit="imgNum"
      :accept="acceptString"
      :http-request="submitUpload"
    >
      <el-icon class="avatar-uploader-icon"><Plus /></el-icon>
    </el-upload>

    <el-button class="ml-3" type="success" @click="submitUpload">
      上传
    </el-button>
    <!-- 上传提示 -->
    <div class="el-upload__tip" v-if="showTip">
      请上传
      <template v-if="fileSize">
        大小不超过 <b style="color: #f56c6c">{{ fileSize }}MB</b>
      </template>
      <template v-if="fileType">
        格式为 <b style="color: #f56c6c">{{ fileType.join("/") }}</b>
      </template>
      的文件
    </div>

    <!-- <ImagePreview ></ImagePreview> -->
    <el-dialog v-model="dialogVisible" title="预览" width="600px">
      <img w-full :src="dialogImageUrl" alt="Preview Image" />
    </el-dialog>
  </div>
</template>

<script lang="ts" setup>
import {
  ref,
  computed,
  useAttrs,
  inject,
  onMounted,
  getCurrentInstance,
  defineEmits,
} from "vue";
import { ElMessage } from "element-plus";
import { Plus } from "@element-plus/icons-vue";
import { genFileId } from "element-plus";
import type { UploadInstance, UploadProps, UploadRawFile } from "element-plus";
import { uploadImage } from "@/api/page/home";
import { watch, watchEffect } from "vue";
import { imgIsExternal, isExternal, isArray } from "@/utils/validate.js";
import { deleteOssFile } from "@/api/page/home.js";

const props = defineProps({
  // 图片路径
  imageUrl: String,
  modelValue: [String, Object, Array],
  // 大小限制(MB)
  fileSize: {
    type: Number,
    default: 5,
  },
  // 文件类型, 例如['png', 'jpg', 'jpeg']
  fileType: {
    type: Array,
    default: () => ["png", "jpg", "jpeg", "webp"],
  },
  // 是否显示提示
  isShowTip: {
    type: Boolean,
    default: true,
  },
  imgNum: {
    type: Number,
    default: 1,
  },
  fileId: {
    type: Number,
    require: true,
  },
  fileUploadType: {
    type: String,
    require: true,
  },
});
const uploadRef = ref<UploadInstance>();
// 预览用的图片地址
const dialogImageUrl = ref("");
const dialogVisible = ref(false);
const emit = defineEmits(["file"]);
// 文件列表
const fileList = ref([]);

interface DataForm {
  name: string;
  file: UploadRawFile | null; // 确保 file 字段能够接受 UploadRawFile 类型的对象
}
const dataForm = ref<DataForm>({
  name: "",
  file: null,
});

// 文件类型
const acceptString = computed(() => {
  // 1. 确保每个文件类型前有 '.' 并过滤空值
  const validTypes = props.fileType
    .map((type) => `.${type.trim()}`)
    .filter((type) => type.length > 1 && !type.includes(" "));

  // 2. 使用逗号连接（自动过滤空字符串）
  return validTypes.join(",");
});

// 获取图片数据
// 将获取的图片数据加入fileList中，预览图片数组
const getfileList = () => {
  // 判断父组件的传递数据是否为null
  if (!props.imageUrl) {
    return;
  }
  let urls = [];
  // 1. props.imageUrl 可能是一个字符串地址
  if (props.imgNum <= 1 && props.imageUrl) {
    // 如果链接为外部链接
    if (imgIsExternal(props.imageUrl)) {
      // 直接将链接加入urls(fileList)中
      urls = [props.imageUrl];
    }
    // 链接为本地链接
    else {
      let type = props.imageUrl.split("/").slice(-2, -1)[0];
      let name = props.imageUrl.split("/").pop();
      urls = [
        new URL(`../../assets/file/${type}/${name}`, import.meta.url).href,
      ];
    }
  }
  // 2.当传入的字符串为多个地址时，
  let imgUrlArray = props.imageUrl.split(",");
  if (imgUrlArray.length > 1 && isArray(imgUrlArray)) {
    // 循环每个url，判断是否为外链
    imgUrlArray.forEach((url) => {
      // 如果链接为外部链接
      if (imgIsExternal(url)) {
        // 直接将链接加入urls(fileList)中
        urls.push(url);
      }
      // 链接为本地链接
      else {
        let type = url.split("/").slice(-2, -1)[0];
        let name = url.split("/").pop();
        urls.push(
          new URL(`../../assets/file/${type}/${name}`, import.meta.url).href
        );
      }
    });
  }
  // console.log("预览图片地址:", urls);
  fileList.value = Array.isArray(urls) ? urls.map((url) => ({ url })) : [];
  // return Array.isArray(urls) ? urls.map((url) => ({ url })) : [];
};

onMounted(() => {
  getfileList();
});

// 监听父组件传递的图片地址列表的变化,第一次变化
watch(
  () => props.imageUrl,
  (newVal) => {
    getfileList();
  }
);

// 获取是否显示提示信息
const showTip = computed(
  () => props.isShowTip && (props.fileType || props.fileSize)
);

// 文件移除时的钩子
const handleRemove: UploadProps["onRemove"] = (uploadFile, uploadFiles) => {
  console.log("文件移除", uploadFile, uploadFiles);
  let fileName = uploadFile.url;

  if (fileName) {
    // 获取文件名
    fileName = fileName.split("/").pop();
    console.log("fileName:", fileName);
    // 将当前文件名变为数组
    let imgData = [];
    imgData.push(fileName);
    // 根据文件名，删除存储数据
    deleteOssFile(imgData);
  }
};

// 文件状态改变时的钩子，添加文件、上传成功和上传失败时都会被调用
const handleImgChange: UploadProps["onChange"] = (uploadFile, uploadFiles) => {
  // 判断文件类型
  let isImg = false;
  let rawFile = uploadFile.raw!;
  if (props.fileType.length) {
    let fileExtension = "";
    if (rawFile.name.lastIndexOf(".") > -1) {
      fileExtension = rawFile.name.slice(rawFile.name.lastIndexOf(".") + 1);
    }
    isImg = props.fileType.some((type) => {
      // console.log("type:", type);
      if (fileExtension && fileExtension == type) {
        return true;
      }
    });
  }
  if (!isImg) {
    ElMessage.error(
      `文件格式不正确, 请上传${props.fileType.join("/")}图片格式文件!`
    );
    uploadRef.value!.clearFiles();
  } else {
    console.log("uploadFile", uploadFile);
    dataForm.value.name = uploadFile.raw!.name;
    dataForm.value.file = uploadFile.raw!;
  }
};
//  文件超出个数限制时的钩子（覆盖上传）
const handleExceed: UploadProps["onExceed"] = (files) => {
  uploadRef.value!.clearFiles();
  const file = files[0] as UploadRawFile;
  file.uid = genFileId();
  uploadRef.value!.handleStart(file);
};
// 上传文件之前的钩子，参数为上传的文件，若返回 false 或者返回 Promise 且被 reject，则停止上传。
const beforeAvatarUpload: UploadProps["beforeUpload"] = (rawFile) => {
  // 判断文件后缀
  let isImg = false;
  if (props.fileType.length) {
    let fileExtension = "";
    if (rawFile.name.lastIndexOf(".") > -1) {
      fileExtension = rawFile.name.slice(rawFile.name.lastIndexOf(".") + 1);
    }
    isImg = props.fileType.some((type) => {
      if (rawFile.type.indexOf(type) > -1) return true;
      if (fileExtension && fileExtension.indexOf(type) > -1) return true;
      return false;
    });
  } else {
    isImg = rawFile.type.indexOf("image") > -1;
  }
  if (!isImg) {
    ElMessage.error(
      `文件格式不正确, 请上传${props.fileType.join("/")}图片格式文件!`
    );
    return false;
  }

  // if (rawFile.type !== "image/jpeg" && rawFile.type !== "image/png") {
  //   ElMessage.error("文件格式不正确!");
  //   return false;
  // }

  if (rawFile.size / 1024 / 1024 > 5) {
    ElMessage.error("文件大小超过5M!");
    return false;
  }
  return true;
};
// 预览
const handlePictureCardPreview: UploadProps["onPreview"] = (uploadFile) => {
  dialogImageUrl.value = uploadFile.url!;
  dialogVisible.value = true;
};

// 文件上传失败的回调
const handleAvatarError: UploadProps["onError"] = (error, uploadFile) => {
  ElMessage.error("上传失败!");
};

// 文件提交
const submitUpload: UploadProps["httpRequest"] = async (file) => {
  console.log("uploadRef", dataForm.value);
  let ImgFile = dataForm.value.file;

  // 检查文件是否有效
  if (!(ImgFile instanceof File)) {
    ElMessage.info("请点击图片上传!");
    // console.error("无效的文件,点击图片上传!");
    return;
  }
  let formData = new FormData();
  formData.append("file", ImgFile);
  // 调用上传的方法
  uploadImage(formData).then((res) => {
    if (res.code == 200) {
      ElMessage.success("上传成功!");
      let filePath = res.filePath;
      emit("filePath", filePath);
    }
    if (res.code == 500) {
      ElMessage.error("上传失败!");
    }
  });
  // 将文件信息传给父组件,加上文件名
  // emit("file", dataForm.value);
  // 清除上传组件的数据，不清除展示的文件列表
  // clearFileList();
};

// 上传文件后的清空
const clearFileList = () => {
  uploadRef.value!.clearFiles();
  fileList.value = [];
};

// 将清除文件列表的方法暴露给父组件
defineExpose({
  clearFileList,
});
</script>

<style scoped lang="scss">
.component-upload-image {
  display: columns;
  align-items: center;
  justify-content: center;
  .avatar-uploader {
    width: 100%;
    height: 100%;
    display: block;
  }
  .avatar-uploader .el-upload {
    border: 1px dashed var(--el-border-color);
    border-radius: 6px;
    cursor: pointer;
    position: relative;
    overflow: hidden;
    transition: var(--el-transition-duration-fast);
  }

  .avatar-uploader .el-upload:hover {
    border-color: var(--el-color-primary);
  }

  .el-icon.avatar-uploader-icon {
    font-size: 28px;
    color: #8c939d;
    width: 178px;
    height: 178px;
    text-align: center;
  }
  .ml-3 {
    margin-top: 5px;
  }
}
</style>
